/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = mysql_core.h                                                  */
/*  NOTE      =                                                               */
/*  DATE      = 2015/03/20 by guojq                                           */
/******************************************************************************/
#ifndef _MYSQL_CORE_H_
#define _MYSQL_CORE_H_

#include "frmem.h"
#include "frstr.h"
#include "frcomm.h"
#include "frlist.h"
#include "frhash2.h"
#include "frlog.h"
#include "iconv2utf8.h"
#include "frsutl.h"
#include "frhex_dump.h"

#include "conntrack.h"
#include "module.h"
#include "frct_comm.h"
#include "frdb_cursor.h"
#include "frreport_comm.h"
#include "frbyte_buffer.h"

#define MYSQL_TRUE                                    0
#define MYSQL_FALSE                                   1

#define MYSQL_VERSION_UNKNOWN                         0
#define MYSQL_VERSION_OLD                             1
#define MYSQL_VERSION_NEW                             2

#define MYSQL_REQUEST                                 0
#define MYSQL_RESPONSE                                1

#define MYSQL_RESPONSE_OK                             0
#define MYSQL_RESPONSE_ERR                            1
#define MYSQL_RESPONSE_EOF                            2
#define MYSQL_RESPONSE_SKIP                           3
#define MYSQL_RESPONSE_RECEIVE                        4

#define MYSQL_RESPONSE_NORMAL                         0
#define MYSQL_RESPONSE_RESULT_FIELD                   1
#define MYSQL_RESPONSE_RESULT_EOF                     2
#define MYSQL_RESPONSE_RESULT_ROW                     3
#define MYSQL_RESPONSE_RESULT_ROW_EOF                 4

#define MYSQL_REQUEST_LONGIN                          1
#define MYSQL_REQUEST_START                           2

#define MYSQL_LOGIN_UNKNOWN                           0
#define MYSQL_LOGIN_FAIL                              1
#define MYSQL_LOGIN_SUCC                              2

#define MYSQL_REPORT_KEY_DBNAME                       "mysql.dbname"

typedef enum mysql_state {
	UNDEFINED,
	LOGIN,
	REQUEST,
	RESPONSE_OK,
	RESPONSE_MESSAGE,
	RESPONSE_TABULAR,
	RESPONSE_SHOW_FIELDS,
	FIELD_PACKET,
	ROW_PACKET,
	RESPONSE_PREPARE,
	PREPARED_PARAMETERS,
	PREPARED_FIELDS
} Mysql_state_t;

typedef struct __st_L7session_mysql {
    int  i_version;                 //版本号
    char *p_charset;                //charset
    char *p_db_user;                //用户名
    char *p_db_name;                //数据库名
    int  i_login;                   //登录是否成功
    int  i_greet;                   //是否做过会话
    struct timeval st_login;        //登录时间
    
} L7session_mysql;

/*
 *  分片包数据
*/
typedef struct __st_L7_fragment_mysql {
    int i_remain_head_len;                /* 残留packet的头数据长度 */
    char arr_remain_packet_head[8];       /* 残留packet的头数据 */
    uint64_t u64_total_len;               /* 实际数据总长度 */
    uint64_t u64_remain_len;              /* 还需要接受的数据长度 */
    uint64_t u64_skip_len;                /* 还需要跳过的数据长度 */
    uint64_t u64_parsed_index;            /* 解析到的位置 */
    Frbyte_Packet *p_st_data;             /* packet数据 */
    struct timeval st_first_timestamp;    /* 第一个分片包的时间 */
    struct timeval st_end_timestamp;      /* 最后一个分片包的时间 */
} L7_fragment_mysql;

/*
 *  mysql请求
 *  对应L7_requestdata中的p_request_private数据
*/
typedef struct __st_L7_req_mysql {
    uint8_t u8_request_type;              /* request类型 */
    Sql_statement *p_st_statement;        /* 对应游标数据 */
    Sql_resultset *p_st_resultset;        /* 对应结果集索引 */
    uint8_t u8_whole_flag;                /* 本次请求是否已全部接收 */
} L7_req_mysql;

/*
 *  mysql响应
 *  解析response过程中的数据
*/
typedef struct __st_L7_resp_mysql {
    int  i_status;                        /* 响应状态 */
    long long ll_error_num;               /* 错误号 */
    char *p_error_msg;                    /* 错误信息 */
    unsigned int ui_response_count;       /* 响应个数 */
    unsigned long arr_effect_rows[1024];      /* 响应值 */
    Sql_statement *p_st_statement;        /* 对应游标数据 */
    uint8_t u8_whole_flag;                /* 本次响应是否已全部接收 */
    
    long long ll_field_count;             /* 列信息个数 */
    Frlist_header st_row_header;          /* row信息 */
} L7_resp_mysql;

/*
 *  MYSQL私有数据
*/
typedef struct __st_L7session_mysql_private {
    int i_in_session;                     /* session flag */
    L7_fragment_mysql *p_st_fragment;     /* 分片包数据 */
    L7session_mysql *p_st_sess;           /* session数据 */
    L7_req_mysql *p_st_req;               /* request数据 */
    L7_resp_mysql *p_st_resp;             /* 临时response信息 */
} L7session_mysql_private;


Frreport_body_data* mysql_new_report_body(Conntrack *p_st_conn
                                        , L7session_mysql *p_st_sess);
                                        
int mysql_create_session_data(L7session_mysql *p_st_session
                                 , Frlist_header **pp_lst_session_data);
int mysql_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet);
int mysql_analysis(Conntrack *p_st_conn
                  , Apm_packet *p_st_packet
                  , Frhash_header *p_st_hash_report);
int mysql_session_destroy(void *p_private_session);

#endif
